using System;
using System.IO;
using System.Reflection;
using NUnit.Framework;
using ODX.Core;
using ODX.LazyUnitTester;

namespace Polymorphy

{
    //[Table]
    //[HierarchyRoot]
    //[TypeDef("D")]
    //public abstract class Department : Entity
    //{
    //    public abstract string Name { get; set; }
    //}

    //[TypeDef("U")]
    //public abstract class Unit : Department
    //{
    //    public abstract string Account { get; set; }
    //}

    //[Table]
    //public abstract class Busines : Unit
    //{
    //    public abstract string Owner { get; set; }
    //}

    [Table("Cart")]
    public abstract class Cart : Entity
    {
        [Column("CartID")]
        public abstract IEntityList<Merchandise> Goods { get; }
    }

    [Table("Merchandise")]
    [HierarchyRoot]
    public abstract class Merchandise : Entity
    {
        public abstract string Name { get; set; }
        public abstract decimal Price { get; set; }
    }

    [Table("Oven")]
    [TypeDef("O")]
    public abstract class Oven : Merchandise
    {
        public abstract double Power { get; set; }
    }

    [Table("PhotoCam")]
    public abstract class PhotoCam : Merchandise
    {
        public abstract bool IsProfessional { get; set; }
    }

    [Table("FilmCam")]
    [TypeDef("FC")]
    public abstract class FilmCam : PhotoCam
    {
        public abstract double FilmSize { get; set; }
    }

    [Table("DigitalCam")]
    [TypeDef("DC")]
    public abstract class DigitalCam : PhotoCam
    {
        public abstract int Resolution { get; set; }
    }

    [TestFixture]
    public class C05_Polymorphy
    {
        [TestBody]
        static void Main()
        {
            string filename = "polymorphy.xml";
            if ( File.Exists(filename) )
                File.Delete(filename);

            Session session = new Session(new XmlDataProvider(filename));
            session.RegisterAssembly(Assembly.GetExecutingAssembly());
            session.Prepare();

            Cart cart = session.Create<Cart>();

            Oven oven = session.Create<Oven>();
            oven.Name = "Magic Oven";
            oven.Price = 123.99m;
            oven.Power = 800;

            FilmCam filmCam = session.Create<FilmCam>();
            filmCam.Name = "Dream Cam";
            filmCam.Price = 999.99m;
            filmCam.IsProfessional = true;
            filmCam.FilmSize = 35;

            DigitalCam digitalCam = session.Create<DigitalCam>();
            digitalCam.Name = "Fancy Cam";
            digitalCam.Price = 234.49m;
            digitalCam.IsProfessional = false;
            digitalCam.Resolution = 8000000;

            cart.Goods.Add(oven, filmCam, digitalCam);

            session.Save();

            Session readerSession = session.Clone();

            Cart rCart = readerSession.SelectOne<Cart>();

            foreach ( Merchandise m in rCart.Goods )
            {
                LUT.WriteLine("Good '{0}' is for ${1}. Type is {2}", m.Name, m.Price, m.GetType().FullName);
                if ( m is Oven )
                    LUT.WriteLine("The oven power is {0} W", (m as Oven).Power);
                if ( m is PhotoCam )
                    LUT.WriteLine("The photo cam is {0}", (m as PhotoCam).IsProfessional ? "professional" : "amateur");
                if (m is FilmCam)
                    LUT.WriteLine("Film size is {0}", (m as FilmCam).FilmSize);
                if (m is DigitalCam)
                    LUT.WriteLine("Matrix resolution is {0} MPx", (m as DigitalCam).Resolution / 1000000.0);

                LUT.WriteLine("----------------------------------------------------");
            }
        }

        [Test]
        public void Test()
        {
            LUT.Execute(Main);
        }
    }
}
